package com.zxd.interview.calc;

import java.io.*;
import java.net.*;
import java.sql.*;
import java.util.*;

public class CalculatorServer {
    private static final int PORT = 12345;
    private static final String DB_URL = "dbc:mysql://19.168.0.100:3306/transaction_tb?useSSL=false&allowPublicKeyRetrieval=true";
    private static final String USER = "xander";
    private static final String PASS = "xander";

    public static void main(String[] args) {
        try (ServerSocket serverSocket = new ServerSocket(PORT)) {
            System.out.println("Server is listening on port " + PORT);
            while (true) {
                new CalculatorHandler(serverSocket.accept()).start();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private static class CalculatorHandler extends Thread {
        private Socket socket;

        public CalculatorHandler(Socket socket) {
            this.socket = socket;
        }

        public void run() {
            try (ObjectInputStream input = new ObjectInputStream(socket.getInputStream());
                 ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream())) {

                while (true) {
                    String request = input.readUTF();
                    if (request.equals("history")) {
                        List<String> history = getHistoryFromDatabase();
                        output.writeObject(history);
                    } else {
                        double result = calculate(request);
                        saveToDatabase(request, result);
                        output.writeDouble(result);
                    }
                    output.flush();
                }

            } catch (IOException | SQLException e) {
                e.printStackTrace();
            }
        }

        private double calculate(String expression) {

            String[] parts = expression.trim().split("\\s+");
            double num1 = Double.parseDouble(parts[0]);
            String operator = parts[1];

            double num2 = 0;
            if (!operator.equals("sqrt")) {
                num2 = Double.parseDouble(parts[2]);
            }

            switch (operator) {
                case "+": return num1 + num2;
                case "-": return num1 - num2;
                case "*": return num1 * num2;
                case "/": return num1 / num2;
                case "^": return Math.pow(num1, num2);
                case "sqrt": return Math.sqrt(num1);
                default: throw new IllegalArgumentException("Invalid operator");
            }
        }


        private void saveToDatabase(String expression, double result) throws SQLException {
            try (Connection conn = DriverManager.getConnection(DB_URL, USER, PASS);
                 PreparedStatement stmt = conn.prepareStatement(
                         "INSERT INTO calculation_history (expression, result) VALUES (?, ?)")) {
                stmt.setString(1, expression);
                stmt.setDouble(2, result);
                stmt.executeUpdate();
            }
        }

        private List<String> getHistoryFromDatabase() throws SQLException {
            List<String> history = new ArrayList<>();
            try (Connection conn = DriverManager.getConnection(DB_URL, USER, PASS);
                 Statement stmt = conn.createStatement();
                 ResultSet rs = stmt.executeQuery("SELECT expression, result FROM calculation_history")) {
                while (rs.next()) {
                    String expression = rs.getString("expression");
                    double result = rs.getDouble("result");
                    history.add(expression + " = " + result);
                }
            }
            return history;
        }
    }
}
